/**
 * echarts图表特效基类
 *
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *
 */


var ecData = require('../util/ecData');
var CircleShape = require('zrender/shape/Circle');
var ImageShape = require('zrender/shape/Image');
var curveTool = require('zrender/tool/curve');
var IconShape = require('../util/shape/Icon');
var SymbolShape = require('../util/shape/Symbol');
var ShapeBundle = require('zrender/shape/ShapeBundle');
var Polyline = require('zrender/shape/Polyline');
var vec2 = require('zrender/tool/vector');
var canvasSupported = require('zrender/tool/env').canvasSupported;
function point(zr, effectList, shape, zlevel) {
    var effect = shape.effect;
    var color = effect.color || shape.style.strokeColor || shape.style.color;
    var shadowColor = effect.shadowColor || color;
    var size = effect.scaleSize;
    var distance = effect.bounceDistance;
    var shadowBlur = typeof effect.shadowBlur != 'undefined' ? effect.shadowBlur : size;
    var effectShape;
    if (shape.type !== 'image') {
        effectShape = new IconShape({
            zlevel: zlevel,
            style: {
                brushType: 'stroke',
                iconType: shape.style.iconType != 'droplet' ? shape.style.iconType : 'circle',
                x: shadowBlur + 1,
                // 线宽
                y: shadowBlur + 1,
                n: shape.style.n,
                width: shape.style._width * size,
                height: shape.style._height * size,
                lineWidth: 1,
                strokeColor: color,
                shadowColor: shadowColor,
                shadowBlur: shadowBlur
            },
            draggable: false,
            hoverable: false
        });
        if (shape.style.iconType == 'pin') {
            effectShape.style.y += effectShape.style.height / 2 * 1.5;
        }
        if (canvasSupported) {
            // 提高性能，换成image
            effectShape.style.image = zr.shapeToImage(effectShape, effectShape.style.width + shadowBlur * 2 + 2, effectShape.style.height + shadowBlur * 2 + 2).style.image;
            effectShape = new ImageShape({
                zlevel: effectShape.zlevel,
                style: effectShape.style,
                draggable: false,
                hoverable: false
            });
        }
    } else {
        effectShape = new ImageShape({
            zlevel: zlevel,
            style: shape.style,
            draggable: false,
            hoverable: false
        });
    }
    ecData.clone(shape, effectShape);
    // 改变坐标，不能移到前面
    effectShape.position = shape.position;
    effectList.push(effectShape);
    zr.addShape(effectShape);
    var devicePixelRatio = shape.type !== 'image' ? window.devicePixelRatio || 1 : 1;
    var offset = (effectShape.style.width / devicePixelRatio - shape.style._width) / 2;
    effectShape.style.x = shape.style._x - offset;
    effectShape.style.y = shape.style._y - offset;
    if (shape.style.iconType == 'pin') {
        effectShape.style.y -= shape.style.height / 2 * 1.5;
    }
    var duration = (effect.period + Math.random() * 10) * 100;
    zr.modShape(shape.id, { invisible: true });
    var centerX = effectShape.style.x + effectShape.style.width / 2 / devicePixelRatio;
    var centerY = effectShape.style.y + effectShape.style.height / 2 / devicePixelRatio;
    if (effect.type === 'scale') {
        // 放大效果
        zr.modShape(effectShape.id, {
            scale: [
                0.1,
                0.1,
                centerX,
                centerY
            ]
        });
        zr.animate(effectShape.id, '', effect.loop).when(duration, {
            scale: [
                1,
                1,
                centerX,
                centerY
            ]
        }).done(function () {
            shape.effect.show = false;
            zr.delShape(effectShape.id);
        }).start();
    } else {
        zr.animate(effectShape.id, 'style', effect.loop).when(duration, { y: effectShape.style.y - distance }).when(duration * 2, { y: effectShape.style.y }).done(function () {
            shape.effect.show = false;
            zr.delShape(effectShape.id);
        }).start();
    }
}
function largePoint(zr, effectList, shape, zlevel) {
    var effect = shape.effect;
    var color = effect.color || shape.style.strokeColor || shape.style.color;
    var size = effect.scaleSize;
    var shadowColor = effect.shadowColor || color;
    var shadowBlur = typeof effect.shadowBlur != 'undefined' ? effect.shadowBlur : size * 2;
    var devicePixelRatio = window.devicePixelRatio || 1;
    var effectShape = new SymbolShape({
        zlevel: zlevel,
        position: shape.position,
        scale: shape.scale,
        style: {
            pointList: shape.style.pointList,
            iconType: shape.style.iconType,
            color: color,
            strokeColor: color,
            shadowColor: shadowColor,
            shadowBlur: shadowBlur * devicePixelRatio,
            random: true,
            brushType: 'fill',
            lineWidth: 1,
            size: shape.style.size
        },
        draggable: false,
        hoverable: false
    });
    effectList.push(effectShape);
    zr.addShape(effectShape);
    zr.modShape(shape.id, { invisible: true });
    var duration = Math.round(effect.period * 100);
    var clip1 = {};
    var clip2 = {};
    for (var i = 0; i < 20; i++) {
        effectShape.style['randomMap' + i] = 0;
        clip1 = {};
        clip1['randomMap' + i] = 100;
        clip2 = {};
        clip2['randomMap' + i] = 0;
        effectShape.style['randomMap' + i] = Math.random() * 100;
        zr.animate(effectShape.id, 'style', true).when(duration, clip1).when(duration * 2, clip2).when(duration * 3, clip1).when(duration * 4, clip1).delay(Math.random() * duration * i)    //.delay(duration / 15 * (15 - i + 1))
.start();
    }
}
function line(zr, effectList, shape, zlevel, isLarge) {
    var effect = shape.effect;
    var shapeStyle = shape.style;
    var color = effect.color || shapeStyle.strokeColor || shapeStyle.color;
    var shadowColor = effect.shadowColor || shapeStyle.strokeColor || color;
    var size = shapeStyle.lineWidth * effect.scaleSize;
    var shadowBlur = typeof effect.shadowBlur != 'undefined' ? effect.shadowBlur : size;
    var effectShape = new CircleShape({
        zlevel: zlevel,
        style: {
            x: shadowBlur,
            y: shadowBlur,
            r: size,
            color: color,
            shadowColor: shadowColor,
            shadowBlur: shadowBlur
        },
        hoverable: false
    });
    var offset = 0;
    if (canvasSupported && !isLarge) {
        // 提高性能，换成image
        var zlevel = effectShape.zlevel;
        effectShape = zr.shapeToImage(effectShape, (size + shadowBlur) * 2, (size + shadowBlur) * 2);
        effectShape.zlevel = zlevel;
        effectShape.hoverable = false;
        offset = shadowBlur;
    }
    if (!isLarge) {
        ecData.clone(shape, effectShape);
        // 改变坐标， 不能移到前面
        effectShape.position = shape.position;
        effectList.push(effectShape);
        zr.addShape(effectShape);
    }
    var effectDone = function () {
        if (!isLarge) {
            shape.effect.show = false;
            zr.delShape(effectShape.id);
        }
        effectShape.effectAnimator = null;
    };
    if (shape instanceof Polyline) {
        var distanceList = [0];
        var totalDist = 0;
        var pointList = shapeStyle.pointList;
        var controlPointList = shapeStyle.controlPointList;
        for (var i = 1; i < pointList.length; i++) {
            if (controlPointList) {
                var cp1 = controlPointList[(i - 1) * 2];
                var cp2 = controlPointList[(i - 1) * 2 + 1];
                totalDist += vec2.dist(pointList[i - 1], cp1) + vec2.dist(cp1, cp2) + vec2.dist(cp2, pointList[i]);
            } else {
                totalDist += vec2.dist(pointList[i - 1], pointList[i]);
            }
            distanceList.push(totalDist);
        }
        var obj = { p: 0 };
        var animator = zr.animation.animate(obj, { loop: effect.loop });
        for (var i = 0; i < distanceList.length; i++) {
            animator.when(distanceList[i] * effect.period, { p: i });
        }
        animator.during(function () {
            var i = Math.floor(obj.p);
            var x, y;
            if (i == pointList.length - 1) {
                x = pointList[i][0];
                y = pointList[i][1];
            } else {
                var t = obj.p - i;
                var p0 = pointList[i];
                var p1 = pointList[i + 1];
                if (controlPointList) {
                    var cp1 = controlPointList[i * 2];
                    var cp2 = controlPointList[i * 2 + 1];
                    x = curveTool.cubicAt(p0[0], cp1[0], cp2[0], p1[0], t);
                    y = curveTool.cubicAt(p0[1], cp1[1], cp2[1], p1[1], t);
                } else {
                    x = (p1[0] - p0[0]) * t + p0[0];
                    y = (p1[1] - p0[1]) * t + p0[1];
                }
            }
            effectShape.style.x = x;
            effectShape.style.y = y;
            if (!isLarge) {
                zr.modShape(effectShape);
            }
        }).done(effectDone).start();
        animator.duration = totalDist * effect.period;
        effectShape.effectAnimator = animator;
    } else {
        var x0 = shapeStyle.xStart - offset;
        var y0 = shapeStyle.yStart - offset;
        var x2 = shapeStyle.xEnd - offset;
        var y2 = shapeStyle.yEnd - offset;
        effectShape.style.x = x0;
        effectShape.style.y = y0;
        var distance = (x2 - x0) * (x2 - x0) + (y2 - y0) * (y2 - y0);
        var duration = Math.round(Math.sqrt(Math.round(distance * effect.period * effect.period)));
        if (shape.style.curveness > 0) {
            var x1 = shapeStyle.cpX1 - offset;
            var y1 = shapeStyle.cpY1 - offset;
            effectShape.effectAnimator = zr.animation.animate(effectShape, { loop: effect.loop }).when(duration, { p: 1 }).during(function (target, t) {
                effectShape.style.x = curveTool.quadraticAt(x0, x1, x2, t);
                effectShape.style.y = curveTool.quadraticAt(y0, y1, y2, t);
                if (!isLarge) {
                    zr.modShape(effectShape);
                }
            }).done(effectDone).start();
        } else {
            // 不用 zr.animate，因为在用 ShapeBundle 的时候单个 effectShape 不会
            // 被加到 zrender 中
            effectShape.effectAnimator = zr.animation.animate(effectShape.style, { loop: effect.loop }).when(duration, {
                x: x2,
                y: y2
            }).during(function () {
                if (!isLarge) {
                    zr.modShape(effectShape);
                }
            }).done(effectDone).start();
        }
        effectShape.effectAnimator.duration = duration;
    }
    return effectShape;
}
function largeLine(zr, effectList, shape, zlevel) {
    var effectShape = new ShapeBundle({
        style: { shapeList: [] },
        zlevel: zlevel,
        hoverable: false
    });
    var shapeList = shape.style.shapeList;
    var effect = shape.effect;
    effectShape.position = shape.position;
    var maxDuration = 0;
    var subEffectAnimators = [];
    for (var i = 0; i < shapeList.length; i++) {
        shapeList[i].effect = effect;
        var subEffectShape = line(zr, null, shapeList[i], zlevel, true);
        var subEffectAnimator = subEffectShape.effectAnimator;
        effectShape.style.shapeList.push(subEffectShape);
        if (subEffectAnimator.duration > maxDuration) {
            maxDuration = subEffectAnimator.duration;
        }
        if (i === 0) {
            effectShape.style.color = subEffectShape.style.color;
            effectShape.style.shadowBlur = subEffectShape.style.shadowBlur;
            effectShape.style.shadowColor = subEffectShape.style.shadowColor;
        }
        subEffectAnimators.push(subEffectAnimator);
    }
    effectList.push(effectShape);
    zr.addShape(effectShape);
    var clearAllAnimators = function () {
        for (var i = 0; i < subEffectAnimators.length; i++) {
            subEffectAnimators[i].stop();
        }
    };
    if (maxDuration) {
        effectShape.__dummy = 0;
        // Proxy animator
        var animator = zr.animate(effectShape.id, '', effect.loop).when(maxDuration, { __dummy: 1 }).during(function () {
            zr.modShape(effectShape);
        }).done(function () {
            shape.effect.show = false;
            zr.delShape(effectShape.id);
        }).start();
        var oldStop = animator.stop;
        animator.stop = function () {
            clearAllAnimators();
            oldStop.call(this);
        };
    }
}
module.exports = {
    point: point,
    largePoint: largePoint,
    line: line,
    largeLine: largeLine
} || module.exports;;